{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 安装启动 Docker"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 1. 下载依赖软件\n",
    "\n",
    "```sh\n",
    "yum install -y yum-utils\n",
    "```\n",
    "\n",
    "## 2. 下载 Docker yum 源\n",
    "\n",
    "```sh\n",
    "yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo\n",
    "```\n",
    "\n",
    "## 3. 安装启动 Dokcer\n",
    "\n",
    "```sh\n",
    "yum makecache fast\n",
    "yum -y install docker-ce    # 安装docker-ce(社区版)，EE版要收费\n",
    "systemctl start docker\n",
    "systemctl enable docker\n",
    "\n",
    "```\n",
    "\n",
    "## 4. 验证安装是否成功 (有 client 和 service 两部分表示 docker 安装启动都成功了)\n",
    "\n",
    "```sh\n",
    "docker version\n",
    "```\n",
    "\n",
    "正常显示上下两部分如下内容\n",
    "\n",
    "\n",
    "# 安装数据库\n",
    "\n",
    "\n",
    "## 1. 拉取镜像\n",
    "\n",
    "```sh\n",
    "docker pull mysql:8.0\n",
    "docker images   #查看一下镜像拉取是否成功\n",
    "\n",
    "```\n",
    "\n",
    "## 2. 测试运行\n",
    "\n",
    "此次运行镜像只做测试用，一会再删除\n",
    "\n",
    "```sh\n",
    "docker run -d -p 3306:3306 -e MYSQL_ROOT_PASSWORD=123456 --name t_mysql mysql:8.0\n",
    "\n",
    "docker ps   #查看容器是否正常运行，没有的话可以用 docker ps -a 查看是否创建容器然后用 docker logs 容器ID来查看日志\n",
    "```\n",
    "\n",
    "## 3. 查看各个文件所在的位置\n",
    "\n",
    "```sh\n",
    "docker exec -it t_mysql /bin/bash    #进入容器\n",
    "cd /etc/mysql\n",
    "ls\n",
    "```\n",
    "\n",
    "显示如下：\n",
    "\n",
    "```sh\n",
    "conf.d/\tmy.cnf\tmy.cnf.fallback\n",
    "```\n",
    "\n",
    "查看各个文件的位置\n",
    "\n",
    "```sh\n",
    "cat my.cnf\n",
    "```\n",
    "\n",
    "显示如下：\n",
    "\n",
    "```sh\n",
    "[mysqld]\n",
    "pid-file        = /var/run/mysqld/mysqld.pid\n",
    "socket          = /var/run/mysqld/mysqld.sock\n",
    "datadir         = /var/lib/mysql\n",
    "secure-file-priv= NULL\n",
    "```\n",
    "\n",
    "**解释：**\n",
    "\n",
    "```\n",
    "pid-file       #设置包含运行的named守护进程的进程id的文件位置。\n",
    "socket        #MySQL的通讯协议的载体\n",
    "datadir        #MySQL的数据库文件所在目录\n",
    "secure-file-priv= NULL\n",
    "log-error\t   #MySQL的错误日志\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 映射本地目录\n",
    "\n",
    "通过映射让容器内的配置文件、日志文件、数据文件与本地相对应\n",
    "\n",
    "## 1. 在本地创建对应文件及目录\n",
    "\n",
    "```\n",
    "docker stop t_mysql\n",
    "docker rm -f t_mysql\n",
    "```\n",
    "\n",
    "```sh\n",
    "# 用于存放mysql配置文件\n",
    "mkdir -p /docker/mysql/conf/\n",
    "# 用于存放mysql数据文件\n",
    "mkdir -p /docker/mysql/data/\n",
    "```\n",
    "\n",
    "### MySQL 配置文件\n",
    "\n",
    "```ini\n",
    "[client]\n",
    "port            = 3306\n",
    "socket          = /tmp/mysql.sock\n",
    "[mysqld]\n",
    "datadir=/var/lib/mysql       # mysql默认数据存储目录\n",
    "socket=/tmp/mysql.sock       # mysql服务器连接方式\n",
    "port=3306                    # mysql服务端口\n",
    "sql_mode=\"NO_AUTO_CREATE_USER,NO_ENGINE_SUBSTITUTION\"      # 定义了mysql应该支持的sql语法，数据校验等!  NO_AUTO_CREATE_USER：禁止GRANT创建密码为空的用户。 NO_ENGINE_SUBSTITUTION 如果需要的存储引擎被禁用或未编译，可以防止自动替换存储引擎\n",
    "long_query_time = 5         # 超过的时间为1s；MySQL能够记录执行时间超过参数 long_query_time 设置值的SQL语句，默认是不记录的。\n",
    "slow_query_log = 1          # 开启慢查询\n",
    "slow_query_log_file = slow.log  # 指定慢查询日志保存路径及文件名\n",
    "max_connections=3000       # mysql的最大连接数，MySQL的实际最大可连接数为max_connections+1；MySQL无论如何都会保留一个用于管理员（SUPER）登陆的连接，用于管理员连接数据库进行维护操作，即使当前连接数已经达到了\n",
    "skip-name-resolve          # 跳过客户端域名解析\n",
    "back_log=384               # 在MySQL暂时停止响应新请求之前的短时间内多少个请求可以被存在堆栈中\n",
    "log-bin=mysql-bin          # 开启二进制日志功能，binlog数据位置\n",
    "binlog_format=mixed        # mysql 复制方式：混合模式复制\n",
    "expire_logs_days = 7       # 控制binlog日志文件保留时间，expire_logs_days=7           # 表示保留最近7天的binlog日志，7天以前的binlog日志会被自动删除\n",
    "server-id = 123          # mysql的同步数据中是包含server-id的，用于标识该语句最初从哪个server写入\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 2. 创建容器\n",
    "\n",
    "-v :/etc/my.cnf -v /docker/mysql/data:/var/lib/mysql  \n",
    "\n",
    "```sh\n",
    "docker run -d -p 3306:3306 --privileged=true \\\n",
    "-e MYSQL_ROOT_PASSWORD=123456 \\\n",
    "-v /docker/mysql/conf/my.cnf:/etc/mysql/my.cnf \\\n",
    "-v /opt/data/mysql:/var/lib/mysql \\\n",
    "-v /opt/logs/mysql/error.log:/var/log/mysql/error.log \\\n",
    "--character-set-server=utf8mb4 --collation-server=utf8mb4_general_ci \\\n",
    "--name mysql mysql:8.0\n",
    "\n",
    "```\n",
    "\n",
    "**说明：**\n",
    "\n",
    "- `run`: run 是运行一个容器\n",
    "- `-d`: 表示后台运行\n",
    "- `-p`: 表示容器内部端口和服务器端口映射关联\n",
    "- `--privileged=true`: 设值MySQL 的root用户权限, 否则外部不能使用root用户登陆\n",
    "- `--name mysql`: 设值容器名称为mysql\n",
    "- `mysql:8.0`  表示从docker镜像mysql:8.0 中启动一个容器\n",
    "- `--character-set-server=utf8mb4 --collation-server=utf8mb4_general_ci`:   设值数据库默认编码\n",
    "- `-v /docker/mysql/conf/my.cnf:/etc/my.cnf`   将服务器中的my.cnf配置映射到docker中的/docker/mysql/conf/my.cnf配置\n",
    "- `-v /docker/mysql/data:/var/lib/mysql`　　　　同上,映射数据库的数据目录, 避免以后docker删除重新运行MySQL容器时数据丢失\n",
    "- `-e MYSQL_ROOT_PASSWORD=123456`　:设置MySQL数据库root用户的密码\n",
    "\n",
    "## 测试\n",
    "\n",
    "1. 创建容器成功后查看一下/opt/data/mysql 下是否有文件\n",
    "\n",
    "```sh\n",
    "docker exec -it test_mysql /bin/bash  #进入容器查看配置文件是否同步\n",
    "cat /etc/mysql/my.cnf\n",
    "```\n",
    "\n",
    "执行MySQL命令, 输入root密码, 连接MySQL\n",
    "\n",
    "```sh\n",
    "mysql -u root -p\n",
    "123456\n",
    "show databases;\n",
    "```\n",
    "\n",
    "2. 测试数据库文件是否映射正确"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# 其他\n",
    "\n",
    "## 解决Docker中mysql修改配置导致无法启动的docker容器\n",
    "\n",
    "宿主机中查找my.cnf文件\n",
    "\n",
    "```sh\n",
    "find / -name my.cnf |grep '/etc/mysql/my.cnf'\n",
    "```\n",
    "\n",
    "找到：\n",
    "```\n",
    "/data/docker/overlay2/dfc2ddbed53a1237fa120f7b9a79eb4488bd3d2ff2ae7f4ce6052ba5b52b480a/diff/etc/mysql/my.cnf\n",
    "```\n",
    "#vi 修改如上找到的文件即可\n",
    "或到目录\n",
    "/data/docker/overlay2/dfc2ddbed53a1237fa120f7b9a79eb4488bd3d2ff2ae7f4ce6052ba5b52b480a/diff/etc/mysql/下，如果有my.cnf.fallback\n",
    "可以执行\n",
    "\n",
    "```sh\n",
    "mv my.cnf.fallback my.cnf\n",
    "```"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 优化 mysql内存占用\n",
    "\n",
    "1. 进入docker bash\n",
    "\n",
    "```sh\n",
    "$ docker exec -it mysql bash\n",
    "```\n",
    "\n",
    "2. 进入 /etc/mysql/conf.d  \n",
    "3. 安装 Vim\n",
    "\n",
    "```sh\n",
    "$ apt-get update\n",
    "$ apt-get install vim \n",
    "```\n",
    "4. vim docker.cnf，追加以下内容\n",
    "\n",
    "```ini\n",
    "[mysqld]\n",
    "performance_schema = off  # 加入这一行即可\n",
    "performance_schema_max_table_instances=400  \n",
    "table_definition_cache=400  \n",
    "table_open_cache=256\n",
    "```\n",
    "\n",
    "按Esc :wq! 退出vim\n",
    "\n",
    "退出bash， 重启mysql\n",
    "\n",
    "```sh\n",
    "docker restart mysql \n",
    "```"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "---\n",
    "---\n",
    "\n",
    "```sh\n",
    "mkdir -p /docker/mysql/data\n",
    "mkdir -p /docker/mysql/conf\n",
    "\n",
    "\n",
    "# ......\n",
    "\n",
    "docker run -d -p 3306:3306 --privileged=true \\\n",
    "-e MYSQL_ROOT_PASSWORD=123456 \\\n",
    "-v /docker/mysql/data:/var/lib/mysql \\\n",
    "-v /docker/mysql/logs/error.log:/var/log/mysql/error.log \\\n",
    "--name mysql mysql:8.0 \\\n",
    "--character-set-server=utf8mb4 --collation-server=utf8mb4_general_ci\n",
    "\n",
    "#创建挂载目录\n",
    "mkdir -p /docker/gogs\n",
    "\n",
    "docker run -d -p 9022:22 -p 9080:3000 \\\n",
    "--link mysql:mysql \\\n",
    "-v /docker/gogs:/data \\\n",
    "--name=tjkj-gogs2 \\\n",
    "gogs/gogs\n",
    "```"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.7.3"
  },
  "toc": {
   "base_numbering": 1,
   "nav_menu": {},
   "number_sections": true,
   "sideBar": true,
   "skip_h1_title": false,
   "title_cell": "Table of Contents",
   "title_sidebar": "Contents",
   "toc_cell": false,
   "toc_position": {
    "height": "calc(100% - 180px)",
    "left": "10px",
    "top": "150px",
    "width": "220.182px"
   },
   "toc_section_display": true,
   "toc_window_display": true
  },
  "varInspector": {
   "cols": {
    "lenName": 16,
    "lenType": 16,
    "lenVar": 40
   },
   "kernels_config": {
    "python": {
     "delete_cmd_postfix": "",
     "delete_cmd_prefix": "del ",
     "library": "var_list.py",
     "varRefreshCmd": "print(var_dic_list())"
    },
    "r": {
     "delete_cmd_postfix": ") ",
     "delete_cmd_prefix": "rm(",
     "library": "var_list.r",
     "varRefreshCmd": "cat(var_dic_list()) "
    }
   },
   "types_to_exclude": [
    "module",
    "function",
    "builtin_function_or_method",
    "instance",
    "_Feature"
   ],
   "window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
